package com.sunther.document.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunther.document.Enum.ExportHeaderEnum;
import com.sunther.document.dao.TermDao;
import com.sunther.document.entity.TermEntity;
import com.sunther.document.service.DictService;
import com.sunther.document.service.ProjectService;
import com.sunther.document.service.TermService;
import com.sunther.document.util.ExportExcelUtil;
import com.sunther.document.util.UserInfoUtil;
import com.sunther.idb.common.util.WebResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author csb
 * @description: TODO
 * @date 2023/5/19 10:00
 */
@Service
public class TermServiceImpl extends ServiceImpl<TermDao, TermEntity> implements TermService {

    @Autowired
    private TermDao termDao;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private DictService dictService;

    @Override
    public Page pageList(String keyword, String projectId, Integer speciality, int pageNumber, int pageSize) {
        Page userPage = new Page(pageNumber,pageSize);
        QueryWrapper<TermEntity> wrapper = new QueryWrapper<>();

        if (StrUtil.isNotBlank(keyword)){
            wrapper.and(wrap -> wrap.like("name_ch",keyword).or().like("name_en",keyword));
        }
        if (StrUtil.isNotBlank(projectId)){
            wrapper.in("project_id",projectId);
        }
        if (null != speciality){
            wrapper.eq("speciality",speciality);
        }
        wrapper.orderByDesc("update_time");
        Page page = termDao.selectPage(userPage, wrapper);

        getText(page.getRecords());
        return page;
    }

    private void getText(List<TermEntity> records) {

        Map<String, String> projectNameMap = projectService.getAllProjectNameMap();
        Map<Integer, String> speciality = dictService.getMapByType("speciality");

        records.stream().forEach(a -> {
            StringBuilder strBuilder = new StringBuilder();
            Set<String> projectIds = a.getProjectId();
            projectIds.stream().forEach(b -> {
                if (null != projectNameMap.get(b)){
                    strBuilder.append(projectNameMap.get(b)).append(",");
                }
            });
            if(strBuilder.length() > 0){
                strBuilder.deleteCharAt(strBuilder.length()-1);
            }
            a.setProjectText(strBuilder.toString());
            a.setSpecialityText(speciality.get(a.getSpeciality()));
        });
    }

    @Override
    public WebResult saveData(TermEntity data, HttpServletRequest request) {
        try {
            Integer userId = UserInfoUtil.getUserId(request);

            //中文 英文 专业确定唯一性
            QueryWrapper<TermEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("name_ch",data.getNameCh());
            wrapper.eq("name_en",data.getNameEn());
            wrapper.eq("speciality",data.getSpeciality());
            if (null != data.getId()){
                wrapper.ne("id",data.getId());
            }
            long count = count(wrapper);
            if (count > 0) {
                return WebResult.failure("术语重复");
            }
            if (null == data.getId()){
                data.init(String.valueOf(userId));
            }else {
                data.modify(String.valueOf(userId));
            }
            saveOrUpdate(data);
            return WebResult.success("操作成功");
        }catch (Exception e) {
            return WebResult.failure("操作失败");
        }
    }

    @Override
    public void export(String keyword, String projectId, Integer speciality, HttpServletResponse response) throws Exception {
        List<TermEntity> list = pageList(keyword, projectId, speciality, 1, 9999).getRecords();
        String title = "术语库";
        String[] rowName = ExportHeaderEnum.TERM_ROW_NAME;
        List<Object[]> dataList = new ArrayList<>();

        int i = 0;
        for (TermEntity entity : list) {
            Object[] obj = new Object[rowName.length];
            obj[0] = i++;
            obj[1] = entity.getNameCh();
            obj[2] = entity.getNameEn();
            obj[3] = entity.getSpecialityText();
            obj[4] = entity.getProjectText();
            dataList.add(obj);
        }

        ExportExcelUtil exportExcelUtil = new ExportExcelUtil(title, rowName, dataList, response);
        exportExcelUtil.export();
    }

    @Override
    public TermEntity dtl(Integer id) {
        TermEntity termEntity = getById(id);
        ArrayList<TermEntity> list = new ArrayList<>();
        list.add(termEntity);
        getText(list);
        return list.get(0);
    }

    @Override
    public WebResult upload(MultipartFile file, HttpServletRequest request) throws IOException {
        Integer userId = UserInfoUtil.getUserId(request);
        // 通过文件获取输入流
        InputStream in = file.getInputStream();
        // 借助hutool读取
        ExcelReader reader = ExcelUtil.getReader(in);
        // 从第二行开始读
        List<List<Object>> list = reader.read(3);

        if(null == list || list.size() < 1){
            return WebResult.failure("异常，未获取到数据");
        }

        List<TermEntity> terms = CollUtil.newArrayList();
        Map<String, Integer> speciality = dictService.getMapNameByType("speciality");
        Map<String, String> projectName = projectService.getAllProjectNameByNameMap();
        // 遍历
        int i = 1;
        for (List<Object> row : list) {
            TermEntity term = new TermEntity();
            // 转换成字符串
            term.setNameCh(row.get(1).toString());
            term.setNameEn(row.get(2).toString());
            if (null == speciality.get(row.get(3).toString())){
                return WebResult.failure("第"+i+"条数据的所属专业不存在，请检查");
            }
            if (null == projectName.get(row.get(4).toString())){
                return WebResult.failure("第"+i+"条数据的所属项目不存在，请检查");
            }
            term.setSpeciality(speciality.get(row.get(3).toString()));
            term.setProjectIdUpload(projectName.get(row.get(4).toString()));

            terms.add(term);
            i++;
        }
        //相同术语的去重
        ArrayList<TermEntity> arrayList = new ArrayList<>();
        arrayList = terms.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(o -> o.getNameCh() + "#" + o.getNameEn() + "#" + o.getSpeciality()))), ArrayList::new));


        //相同术语 项目拼接
        arrayList.stream().forEach(a -> {
            HashSet<String> set = new HashSet<>();
            terms.stream().forEach(b -> {
                if (a.getNameCh().equals(b.getNameCh()) && a.getNameEn().equals(b.getNameEn()) && a.getSpeciality().equals(b.getSpeciality())){
                    set.add(b.getProjectIdUpload());
                }
            });
            a.setProjectId(set);
            a.init(String.valueOf(userId));
        });

        //判断是否存在重复术语  重复就做更新
        Map<String, List<TermEntity>> map = repeatData(arrayList,userId);

        List<TermEntity> update = map.get("update");
        List<TermEntity> insert = map.get("insert");

        saveBatch(insert);
        updateBatchById(update);

        return WebResult.success("操作成功,成功新增 "+insert.size() +" 条术语，更新 "+update.size()+" 条术语",map);
    }

    /**
     * 判断是否重复术语
     */
    private Map<String, List<TermEntity>> repeatData(List<TermEntity> treeSet, Integer userId) {

        HashMap<String, List<TermEntity>> map = new HashMap<>();

        List<String> nameCh = treeSet.stream().map(TermEntity::getNameCh).collect(Collectors.toList());
        List<String> nameEn = treeSet.stream().map(TermEntity::getNameEn).collect(Collectors.toList());
        List<Integer> spe = treeSet.stream().map(TermEntity::getSpeciality).collect(Collectors.toList());

        QueryWrapper<TermEntity> wrapper = new QueryWrapper<>();
        wrapper.in("name_ch",nameCh);
        wrapper.in("name_en",nameEn);
        wrapper.in("speciality",spe);

        List<TermEntity> listUpdate = list(wrapper);

        listUpdate.stream().forEach(a -> {
            HashSet<String> set = new HashSet<>();
            treeSet.stream().forEach(b -> {
                if (a.getNameEn().equals(b.getNameEn()) && a.getNameCh().equals(b.getNameCh()) && a.getSpeciality().equals(b.getSpeciality())){
                    set.addAll(a.getProjectId());
                    set.addAll(b.getProjectId());
                    a.setProjectId(set);
                    a.modify(String.valueOf(userId));
                }
            });
            Iterator<TermEntity> iterator = treeSet.iterator();
            if (iterator.hasNext()) {
                TermEntity next = iterator.next();
                if (a.getNameEn().equals(next.getNameEn()) && a.getNameCh().equals(next.getNameCh()) && a.getSpeciality().equals(next.getSpeciality())){
                    iterator.remove();
                }
            }
        });

        map.put("update",listUpdate);
        map.put("insert",treeSet);

        return map;
    }

}
